package com.csl.tools.CommonUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

/**
 * 日期工具类, 继承org.apache.commons.lang.time.DateUtils类
 * 
 */
public class DateUtil extends org.apache.commons.lang.time.DateUtils {
	
	private final static String[] monthArr = {"01","02","03","04","05","06","07","08","09","10","11","12"};
	
	private static String[] parsePatterns = {
		 "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",  "yyyy-MM-dd",   "yyyy-MM", 
		 "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm",   "yyyy/MM/dd",  "yyyy/MM", 
		 "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm",   "yyyy.MM.dd",  "yyyy.MM",  
		 "yyyyMMddHHmmss",      "yyyyMMddHHmm",      "yyyyMMdd",     "yyyyMM"       
	};

	
	public static Date string_date(Object str) {
		if (str == null){
			return null;
		}
		try {
			return parseDate(str.toString(), parsePatterns);
		} catch (ParseException e) {
			return null;
		}
	}
	
	public static Date string_date(Object str,String pattern) {
		if (str == null||null==pattern) {
			return null;
		}
		try {
			return parseDate(str.toString(), new String[]{pattern});
		} catch (Exception e) {
			return null;
		}
	}
	public static String date_string(Date date) {
		for(String pattern:parsePatterns){
			String d=date_string(date,pattern);
			if(StringUtils.isNotBlank(d)) return d;
		}
		return null;
	}
	public static String date_string(Date date, String pattern) {
		String formatDate = null;
		if (null!=date&&pattern != null ) {
			formatDate = DateFormatUtils.format(date, pattern);
		}
		return formatDate;
	}
	public static Date date_date(Date date) {
		if (date == null) {
			return null;
		}
		for(String pattern:parsePatterns){
			Date d=date_date(date,pattern);
			if(null!=d) return d;
		}
		return null;
	}
	public static Date date_date(Date date,String pattern) {
		if (date == null||null==pattern) {
			return null;
		}
		try {
			String s=date_string(date,pattern);
			return string_date(s, pattern);
		} catch (Exception e) {
			return null;
		}
	}
	
	
	/**
	 * 得到日期年份字符串 格式（yyyy）
	 */
	public static String getYear(Date d) {
		return date_string(d, "yyyy");
	}

	/**
	 * 得到日期月份字符串 格式（MM）
	 */
	public static String getMonth(Date d) {
		return date_string(d, "MM");
	}

	/**
	 * 得到日期字符串 格式（dd）
	 */
	public static String getDay(Date d) {
		return date_string(d, "dd");
	}

	/**
	 * 得到 日期星期字符串 格式（E）星期几
	 */
	public static String getWeekStr(Date d) {
		return date_string(d, "E");
	}
	
	/**
	 * 得到 日期星期字符串 格式（E）星期几
	 */
	public static int getWeekInt(Date d) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(d);
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
		dayOfWeek=dayOfWeek==0?7:dayOfWeek;
		return dayOfWeek;
	}
	
	/**
	 * 得到 当前日期所在月的第几周（自然周）
	 */
	public static int getWeekNo(Date d){
		d=date_date(d,"yyyyMMdd");
		Date startDayOfMonth=getFirstDayOfMonth(d);//月第一天 日期
		Date startDayOfWeek=getMonDayOfWeek(startDayOfMonth);//周一
		
		Date endDayOfWeek=getMonDayOfWeek(d);//周一
		
		int weekNo=1;
		while(startDayOfWeek.getTime()!=endDayOfWeek.getTime()){
			startDayOfWeek=addDays(startDayOfWeek,7);
			weekNo+=1;
		}
		return weekNo;
	}
	
	/**
	 * 当前日期所在月周数（自然周）
	 */
	public static int getWeekTotal(Date d){
		d=date_date(d,"yyyyMMdd");
		Date startDayOfMonth=getFirstDayOfMonth(d);//月第一天 日期
		Date startDayOfWeek=getMonDayOfWeek(startDayOfMonth);//周一
		Date endDateOfMonth=getLastDayOfMonth(d);//月最后一天
		Date endDayOfWeek=getMonDayOfWeek(endDateOfMonth);//周一
		
		int total=1;
		while(startDayOfWeek.getTime()!=endDayOfWeek.getTime()){
			startDayOfWeek=addDays(startDayOfWeek,7);
			total+=1;
		}
		return total;
	}
	
	/**
	 * 当前日期所在周次的天数（自然周）
	 */
	public static int getWeekDays(Date d,int weekNo){
		Date startDayOfMonth=DateUtil.getFirstDayOfMonth(d);
		Date endDayOfMonth=DateUtil.getLastDayOfMonth(d);
		int weekTotal=getWeekTotal(d);
		int days=0;
		if(weekNo==1){
			int weekInt=getWeekInt(startDayOfMonth);
			days=7-weekInt+1;
		}else if(weekNo==weekTotal){
			int weekInt=getWeekInt(endDayOfMonth);
			days=weekInt;
		}else{
			days=7;
		}
		return days;
	}
	
	public static Date getMonDayOfWeek(Date d){
		int weekInt=getWeekInt(d);//获得周几
		return addDays(d,-weekInt+1);//获得周所在周的周一
	}
	
	public static Date getFirstDayOfMonth(Date date){
		 Date d=date_date(date,"yyyyMM");
		 return d;
	}

	public static Date getLastDayOfMonth(Date date){
		 Date d=getFirstDayOfMonth(date);
		 d=addMonths(d,1);
		 d=addDays(d,-1);
	     return d;
	}

	
	/**
	 * 获取过去的天数
	 */
	public static long pastDays(Date date) {
		long t = new Date().getTime() - date.getTime();
		return t / (24 * 60 * 60 * 1000);
	}

	/**
	 * 获取过去的小时
	 */
	public static long pastHour(Date date) {
		long t = new Date().getTime() - date.getTime();
		return t / (60 * 60 * 1000);
	}

	/**
	 * 获取过去的分钟
	 */
	public static long pastMinutes(Date date) {
		long t = new Date().getTime() - date.getTime();
		return t / (60 * 1000);
	}

	

	/**
	 * 两个日期之间的天数
	 */
	public static double getDistanceOfTwoDate(Date before, Date after) {
		long beforeTime = before.getTime();
		long afterTime = after.getTime();
		return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
	}
	
	/**
	 * 增加天数
	 */
	public static Date addDays(Date date, int days) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.DAY_OF_MONTH, days);
		c.getTime();
		return c.getTime();
	}

	/**
	 * 增加小时数
	 */
	public static Date addHours(Date date, int hours) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.HOUR_OF_DAY, hours);
		c.getTime();
		return c.getTime();
	}

	/**
	 * 增加分钟数
	 */
	public static Date addMin(Date date, int min) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MINUTE, min);
		c.getTime();
		return c.getTime();
	}

	
	public static Date addSecond(Date date, int second) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.SECOND, second);
		c.getTime();
		return c.getTime();
	}
	
	/**
	 * 增加月数
	 */
	public static Date addMonths(Date date, int months) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MONTH, months);
		c.getTime();
		return c.getTime();
	}
	
	/**
	 * 转换为时间（天,时:分:秒.毫秒）
	 */
	public static String formatDateTime(long timeMillis) {
		long day = timeMillis / (24 * 60 * 60 * 1000);
		long hour = (timeMillis / (60 * 60 * 1000) - day * 24);
		long min = ((timeMillis / (60 * 1000)) - day * 24 * 60 - hour * 60);
		long s = (timeMillis / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
		long sss = (timeMillis - day * 24 * 60 * 60 * 1000 - hour * 60 * 60
				* 1000 - min * 60 * 1000 - s * 1000);
		return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "."
				+ sss;
	}
	
	
	/**
	 * 获得包含全部月份的数组
	 */
	public static String[] getMonthArray(){
		return monthArr;
	}
	
	/**
	 * 获取给定日期yyyyMMdd的上周一yyyyMMdd //TODO 
	 * @param ymd
	 * @return
	 */
	public static String getPreSunByYmd(String ymd) {
		return "";
	}
	
	/**
	 * yyyyMMdd 转 Date
	 * @param ymd
	 * @return
	 */
	public static Date ymdToDate(String ymd) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		try {
			Date date = sdf.parse(ymd);
			return date;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Date 转 yyyyMMdd
	 * @param date
	 * @return
	 */
	public static String dateToYmd(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String today = sdf.format(date);
		return today;
	}
	
	/**
	 * 获得今天yyyyMMdd
	 */
	public static String getToday() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String today = sdf.format(new Date());
		return today;
	}
	
	/**
	 * 获取周一
	 * @param i 参数i,  0:上周一，-1:上上周一，1下周一
	 * @return yyyyMMdd
	 */
	public static String getMonday(Integer i) {
		Calendar c = Calendar.getInstance();
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		c.add(Calendar.WEEK_OF_MONTH, i);
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		
		return sdf.format(c.getTime());
	}
	
	/**
	 * 获得指定月份yyyyMM范围内所有的周日
	 * @return 返回结果Map内的格式为 <yyyyMMdd, week>
	 */
	public static Map<String, Integer> getWeekends(String begYm, String endYm) {
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		map.put("20160807", 1);
		map.put("20160814", 2);
		map.put("20160821", 3);
		map.put("20160828", 4);
		
		return map;
	}
	
	/**
	 * 将格式为XXXX年XX月的月份格式改为纯数字格式（2016年12月-----201612）
	 */
	public static String getValueByYm(String ym){
		if(!StringUtils.equals(ym, "")&&null!=ym){
			ym = ym.substring(0, 4)+ym.substring(5, 7);
		}
		return ym;
	}
	
	/**
	 * 获得给定日期yyyyMM的最后一天的日期
	 */
	public static String getLastDayOfMonth(String date){
		int year = Integer.valueOf(date.substring(0, 4));
		int month = Integer.valueOf(date.substring(4));
		
		//String new_date = new SimpleDateFormat("yyyyMM").format(new Date());
		Calendar cal = Calendar.getInstance();
		//cal.set(Calendar.YEAR, year);
		//cal.set(Calendar.MONTH, month -1);
		cal.set(year, month-1, 1);
		//cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
		//String d = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		String res=cal.getActualMaximum(Calendar.DATE)+"";
//		针对二月份计算不准确的情况 这里单独处理
//		String res = d.substring(6,8);
//		if(res.equals("03")){
//			res = "28";
//		}
//		if(res.equals("02")){
//			res = "29";
//		}
		return res;
	}

	/**
	 * 得到输入日期所对应的Date对象
	 * @param date like 20090101
	 * @return
	 */
	public static Date getDate(String date) 
	{
		if (date == null || date.length() != 8) {
			throw new RuntimeException("由于缺少必要的参数，系统无法进行指定的换算.");
		}
		String sYear = date.substring(0, 4);
		int year = Integer.parseInt(sYear);
		String sMonth = date.substring(4, 6);
		int mon = Integer.parseInt(sMonth);
		String sDay = date.substring(6, 8);
		int dday = Integer.parseInt(sDay);
		Calendar cal = Calendar.getInstance();
		cal.set(year, mon - 1, dday);
		return cal.getTime();
	}
	
	/**
	 * 返回延迟若干天后，8位的日期字符串，如：20031225
	 * getDateByDate("20030101", 1)  -> 20030102
	 * getDateByDate("20030101", -2) -> 20021230
	 */
	public static String  getDateByDate(String date, int delayDay) 
	{
		try {
			Calendar c = Calendar.getInstance();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			c.setTime(sdf.parse(date));
			c.add(Calendar.DATE, delayDay);
			return sdf.format(c.getTime());
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 获取两个查询月份之间（含开始月份和结束月份）的所有月份列表
	 * @author 
	 * @return
	 */
	public static List<String> InterzoneMonth(String BeginMonth,String EndMonth)
	{
		List<String> MonthList = new ArrayList<String>();
		if(BeginMonth.equals(EndMonth)){
			MonthList.add(BeginMonth+"01");
		}else{
			String beginyear = BeginMonth.substring(0, 4);
			String endyear = EndMonth.substring(0, 4);
			String beginmonth = BeginMonth.substring(4, 6);
			String endmonth = EndMonth.substring(4, 6);
			String month = "";
			int k = 0;
			if(beginyear.equals(endyear)){
				k = Integer.parseInt(endmonth)-Integer.parseInt(beginmonth);
			}else{
				k = (12-Integer.parseInt(beginmonth))+ 
				(12*(Integer.parseInt(endyear)-Integer.parseInt(beginyear)-1))+Integer.parseInt(endmonth);
			}
			for(int i=0;i<=k;i++){
				month = getNextMonth(BeginMonth,i,"");
				MonthList.add(month);
			}
		}
		return MonthList;
	}
	
	/**
	 * 获取输入 月份的下[前] n 月份 返回 6位 like 200901
	 * @param month  like 200901
	 * @param n
	 * @param style 月份格式 如yyyyMMdd yyyy-MM等 默认为yyyyMMdd
	 * @return
	 */
	public static String getNextMonth(String month, int n,String style) 
	{
		if("".equals(style)||style==null){style="yyyyMMdd";}
		if (month == null || "".equals(month) || month.length() != 6) {
			throw new RuntimeException("由于缺少必要的参数，系统无法进行指定的月份换算.");
		}
		try {
			String sYear = month.substring(0, 4);
			int year = Integer.parseInt(sYear);
			String sMonth = month.substring(4, 6);
			int mon = Integer.parseInt(sMonth);
			Calendar cal = Calendar.getInstance();
			cal.set(year, mon - 1, 1);
			cal.add(Calendar.MARCH, n);
			SimpleDateFormat df = new SimpleDateFormat(style);
			return df.format(cal.getTime());
		} catch (Exception e) {
			throw new RuntimeException("进行月份运算时输入得参数不符合系统规格." + e);
		}
	}
	/**
	 * 根据季度获取月份
	 * @param quarter
	 * @return
	 */
	public static String getMonthsByQuarter(Integer quarter) {
		if(quarter == 1) return "01,02,03";
		if(quarter == 2) return "04,05,06";
		if(quarter == 3) return "07,08,09";
		if(quarter == 4) return "10,11,12";
		
		return null;
	}
	
	/**
	 * @param args
	 * @throws ParseException
	 */
	public static void main(String[] args) throws ParseException {
		 System.out.print(DateUtil.getYear(new Date())+"年");
		 System.out.print(DateUtil.getMonth(new Date())+"月 ");
		 System.out.println(DateUtil.getWeekStr(new Date()));
		 
		 long time = new Date().getTime()-string_date("2017-09-10").getTime();
		 System.out.println(time/(24*60*60*1000)); //天
		 
		 //在原来时间增加1分钟
		 System.out.println(date_string(addMin(new Date(), 1),"yyyy-MM-dd HH:mm:ss"));
		
		 //获取当前日期对应的星期几
		 System.out.println(getWeekInt(new Date()));
		
		 String s="20180419";
		 Date d=DateUtil.string_date(s);
		 //获取日期对应的星期如：20180418对应的星期是星期三
		 System.out.println(DateUtil.getWeekInt(d));
		 
		 String month=DateUtil.getMonthsByQuarter(2);
		 System.out.println("2季度对应的月份为："+month);
	}
}
